package cc.rengu.igas.channel.cups.core.service.trans;


import cc.rengu.igas.channel.cups.common.constant.CupsConfigConstant;
import cc.rengu.igas.channel.cups.common.constant.CupsParamConstant;
import cc.rengu.igas.channel.cups.common.constant.CupsTreeNodeConstant;
import cc.rengu.igas.channel.cups.common.enums.RespCodeEnum;
import cc.rengu.igas.channel.cups.core.model.ChnlBizResponse;
import cc.rengu.igas.channel.cups.core.model.CupsField;
import cc.rengu.igas.channel.cups.core.model.CupsFieldBean;
import cc.rengu.igas.channel.cups.core.model.CupsFieldRspBean;
import cc.rengu.igas.channel.cups.core.realize.CupsMacService;
import cc.rengu.igas.channel.cups.core.realize.impl.CupsMacServiceImpl;
import cc.rengu.igas.channel.cups.core.service.base.CancelService;
import cc.rengu.igas.channel.cups.facade.request.ConsumeRefundRequest;
import cc.rengu.igas.channel.cups.facade.response.ConsumeRefundResponse;
import cc.rengu.igas.share.common.util.DateShareUtil;
import cc.rengu.jradp.mods.trmsg.iso8583.MacUtil;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.DstChannelInfo;
import cc.rengu.oltp.service.common.entity.KeyInfo;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.cache.UnifiedCache;
import com.alibaba.fastjson.JSONObject;

import java.util.Map;

/**
 * 一般消费退货
 */
public class CupsConsumeRefundService extends CancelService {

    @Override
    protected Object beforeBizProcess() throws Exception {
        ConsumeRefundRequest consumeRefundRequest = new ConsumeRefundRequest();
        ConvertUtil.convertOutput(consumeRefundRequest);
        rglog.debug("consumeRefundRequest = <{}>", JSONObject.toJSONString(consumeRefundRequest));
        return consumeRefundRequest;
    }

    @Override
    protected ChnlBizResponse callBizService(Object request) throws Exception {
        ConsumeRefundRequest consumeRefundRequest = (ConsumeRefundRequest) request;
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(consumeRefundRequest.getHeader().getInstId(),
                CupsConfigConstant.CUPS_CONF_NODE, CupsConfigConstant.CUPS_DIRECT_FLAG);
        if (sysParam == null) {
            /*未配置默认直连*/
            return inDirectCups(consumeRefundRequest);
        } else if (AppParamConstant.YES.equals(sysParam.getParamValue())) {
            return directCups(consumeRefundRequest);
        } else {
            return inDirectCups(consumeRefundRequest);
        }

    }

    @Override
    protected void afterBizProcess(ChnlBizResponse response) throws Exception {
        ConsumeRefundResponse consumeRefundResponse = (ConsumeRefundResponse) response.getResult();
        ConvertUtil.convertInput(consumeRefundResponse);
    }

    /**
     * 直连cups
     *
     * @param consumeRefundRequest
     * @return
     * @throws Exception
     */
    ChnlBizResponse directCups(ConsumeRefundRequest consumeRefundRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        int iReturnCode = 0;
        String algorithm = null;
        ChnlBizResponse chnlBizResponse = new ChnlBizResponse();
        ConsumeRefundResponse consumeRefundResponse = new ConsumeRefundResponse();
        String instId = consumeRefundRequest.getHeader().getInstId();

        String cupsSsn = consumeRefundRequest.getCupsTraceNo();
        String transDateTime = consumeRefundRequest.getTransDateTime();

        DstChannelInfo dstChannelInfo = (DstChannelInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.DST_CHANNEL_INFO, DstChannelInfo.class);
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(instId,
                CupsConfigConstant.CUPS_CONF_NODE, CupsConfigConstant.CUPS_ALG_TYPE);
        if (sysParam == null) {
            algorithm = XmlConfigUtil.getXmlConfigCacheKeyValue(CupsConfigConstant.CUPS_CONF_NODE, CupsConfigConstant.CUPS_ALG_TYPE);
        } else {
            algorithm = sysParam.getParamValue();
        }
        String termType = null;
        CupsField cupsField = new CupsField();
        //由于名称一致，因此authCode也在此处拷贝接入到cupsField
        BeanUtil.beanCopy(consumeRefundRequest, cupsField);
        cupsField.setMsgType("0220");
        cupsField.setProcCode("200000");
        cupsField.setLocalDate(transDateTime.substring(0, 4));
        cupsField.setLocalTime(transDateTime.substring(4));
        cupsField.setCupsInstCode(consumeRefundRequest.getCupsInstCode());
        cupsField.setAcqInstCode(consumeRefundRequest.getCupsInstCode());
        cupsField.setFwdInstCode(consumeRefundRequest.getFwdInstCode());
        cupsField.setTransDateTime(transDateTime);
        cupsField.setConCode("00");
        cupsField.setMchntNo(cupsField.getCupsMchntNo());
        String tmpAmt = AmountUtil.changeY2F(consumeRefundRequest.getOrderAmt());
        cupsField.setOrderAmt(String.format("%012d", Integer.valueOf(tmpAmt)));
        if (consumeRefundRequest.getTermInfo() != null) {
            termType = consumeRefundRequest.getTermInfo().getDeviceType();
        }
        if (consumeRefundRequest.getOrigAmt() != null) {
            String tmpOrigAmt = String.format("%012d", Integer.valueOf(AmountUtil.changeY2F(consumeRefundRequest.getOrigAmt())));
            String f048AsOa = packF048AsOaField(tmpOrigAmt);
            cupsField.setPrivAddData(HexUtil.StringtoHex(f048AsOa));
        }

        String reseved = packF060Field(null, consumeRefundRequest.getTermRead(), consumeRefundRequest.getIcConCode(),
                null, null, consumeRefundRequest.getTermInfo().getDeviceType(), algorithm);
        cupsField.setReseved(reseved);
        String piSubField = packF104Pi(consumeRefundRequest.getTermInfo());
        if (piSubField != null) {
            cupsField.setTermAttachData(piSubField);
        }

        String cupsF117FieldFlag = XmlConfigUtil.getXmlConfigCacheKeyValue(CupsConfigConstant.CUPS_TEST_CONF_NODE, CupsConfigConstant.CUPS_F117_FIELD_FLAG);
        if (cupsF117FieldFlag != null && AppParamConstant.YES.equals(cupsF117FieldFlag)) {
            String pi117SubField = packF117Ml(consumeRefundRequest.getMchntShortName());
            if (piSubField != null) {
                cupsField.setAdditionalF117Data(pi117SubField);
            }
        }

        String origAcqInstIdCode = consumeRefundRequest.getCupsInstCode();
        if (origAcqInstIdCode.length() < 11) {
            origAcqInstIdCode = String.format("%0" + (11 - origAcqInstIdCode.length()) + "d", 0) + origAcqInstIdCode;
        }
        String origFwdInstCode = consumeRefundRequest.getFwdInstCode();
        if (origFwdInstCode.length() < 11) {
            origFwdInstCode = String.format("%0" + (11 - origFwdInstCode.length()) + "d", 0) + origFwdInstCode;
        }
        cupsField.setOrigData("0200" + consumeRefundRequest.getOrigTxnInfo().getOriCupsTraceNo()
                + consumeRefundRequest.getOrigTxnInfo().getOriTransDateTime() +
                origAcqInstIdCode + origFwdInstCode);
        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.CUPS_MACBLOCK_ORIG_DATA_ELEMTS, cupsField.getOrigData().substring(0, 20));
        CupsFieldBean cupsFieldBean = new CupsFieldBean();
        cupsFieldBean.setCupsField(cupsField);
        ConvertUtil.convertInput(cupsFieldBean);
        /*计算macblock*/
        MacUtil commonMac = (MacUtil) UnifiedCache.get(CupsParamConstant.CUPS_8583_MAC_CACHE_NAME,
                CupsParamConstant.CUPS_8583_MAC_FILE +
                        CupsParamConstant.CUPS_8583_MAC_TYPE_COMMON);
        byte[] macBlock = commonMac.genMacBlock(CupsParamConstant.CUPS_8583_MAC_TYPE_COMMON);
        if (macBlock == null) {
            throw new BizException(RespCodeEnum.GENERATE_MAC_BLOCK_ERROR.getRespCode(), RespCodeEnum.GENERATE_MAC_BLOCK_ERROR.getRespDesc());
        }
        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.CUPS_MAC_BLOCK, new String(macBlock));

        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, consumeRefundRequest.getHeader().getTxnNum());
        iReturnCode = schedule.callService(dstChannelInfo.getDstServiceName(), 0);
        if (98 == iReturnCode) {
            rglog.error("调用银联cups服务<{}>超时，iReturnCode:<{}>", dstChannelInfo.getDstServiceName(), iReturnCode);
            consumeRefundResponse.setRespCode("98");
            consumeRefundResponse.setRespDesc("交易状态未明");
            chnlBizResponse.setResult(consumeRefundResponse);
            return chnlBizResponse;
        } else if (0 != iReturnCode) {
            rglog.error("调用银联全渠道服务<{}>失败，iReturnCode:<{}>", dstChannelInfo.getDstServiceName(), iReturnCode);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        }
        /*还原交易码*/
        String tunlSsn = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.CHANNEL_SEQ_NUM);
        UnifiedCache.remove(CupsParamConstant.CACHE_CUPS_SN, tunlSsn);
        if (0 != iReturnCode) {
            rglog.error("调用银联cups服务失败，iReturnCode:<{}>", iReturnCode);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        }
        CupsFieldRspBean cupsFieldRspBean = new CupsFieldRspBean();
        ConvertUtil.convertOutput(cupsFieldRspBean);
        String mac = cupsFieldRspBean.getCupsFieldRsp().getMac();
        /*生成应答macBlock*/
        byte[] macBlockRsp = commonMac.getMacBlock(CupsParamConstant.CUPS_8583_MAC_TYPE_COMMON);
        CupsMacService cupsMacService = new CupsMacServiceImpl();
        KeyInfo keyInfo = (KeyInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.CUPS_MAC_KEY_INFO, KeyInfo.class);
        boolean flag = cupsMacService.verifyMacString(keyInfo, mac, new String(macBlockRsp));
        if (!flag) {
            rglog.error("验证mac失败");
        }
        consumeRefundResponse.setVerifyMacFlag(flag);
        BeanUtil.beanCopy(cupsFieldRspBean.getCupsFieldRsp(), consumeRefundResponse);
        if (cupsFieldRspBean.getCupsFieldRsp().getSettleDate() != null) {
            consumeRefundResponse.setSettleDate(getCupsSettleDate(cupsFieldRspBean.getCupsFieldRsp().getSettleDate()));
        }
        consumeRefundResponse.setRespCode(cupsFieldRspBean.getCupsFieldRsp().getRespCode());
        if (CupsParamConstant.SUCCESS_CODE.equals(consumeRefundResponse.getRespCode())) {
            consumeRefundResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            consumeRefundResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        }
        chnlBizResponse.setResult(consumeRefundResponse);
        return chnlBizResponse;
    }

    /**
     * 间联cups
     *
     * @param consumeRefundRequest
     * @return
     * @throws Exception
     */
    ChnlBizResponse inDirectCups(ConsumeRefundRequest consumeRefundRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        int iReturnCode = 0;
        String algorithm = null;
        ChnlBizResponse chnlBizResponse = new ChnlBizResponse();
        ConsumeRefundResponse consumeRefundResponse = new ConsumeRefundResponse();
        String traceNo = consumeRefundRequest.getHeader().getTraceNo();
        String instId = consumeRefundRequest.getHeader().getInstId();
        String oriTraceNo = consumeRefundRequest.getOrigTxnInfo().getOriTraceNo();
        /* 流水号规则：8位渠道标识 + 8位日期 + 6位时间 + 2位数据库服务器集群标识 + 2位预留位 + 6位序号 + 调用序号 */
        /*String transDateTime= traceNo.substring(12,22);
        String cupsSsn = traceNo.substring(26,32);*/

        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.SERVICE_SN, traceNo);
        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.ORI_SERVICE_SN, oriTraceNo);
        DstChannelInfo dstChannelInfo = (DstChannelInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.DST_CHANNEL_INFO, DstChannelInfo.class);
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(instId,
                CupsConfigConstant.CUPS_CONF_NODE, CupsConfigConstant.CUPS_ALG_TYPE);
        if (sysParam == null) {
            algorithm = XmlConfigUtil.getXmlConfigCacheKeyValue(CupsConfigConstant.CUPS_CONF_NODE, CupsConfigConstant.CUPS_ALG_TYPE);
        } else {
            algorithm = sysParam.getParamValue();
        }
        String termType = null;
        CupsField cupsField = new CupsField();
        BeanUtil.beanCopy(consumeRefundRequest, cupsField);

        if (consumeRefundRequest.getTermInfo() != null) {
            termType = consumeRefundRequest.getTermInfo().getDeviceType();
        }
        if (consumeRefundRequest.getIcData() != null && !consumeRefundRequest.getIcData().isEmpty()) {
            String icDataLenth = Integer.toHexString(consumeRefundRequest.getIcData().length()).length() == 1
                    ? "0" + Integer.toHexString(consumeRefundRequest.getIcData().length()).toUpperCase() : Integer.toHexString(consumeRefundRequest.getIcData().length()).toUpperCase();
            xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.IC_DATA_LENGTH, icDataLenth);
        }
        String reseved = packF060Field(null, consumeRefundRequest.getTermRead(), consumeRefundRequest.getIcConCode(),
                null, null, consumeRefundRequest.getTermInfo().getDeviceType(), algorithm);
        cupsField.setReseved(reseved);

        CupsFieldBean cupsFieldBean = new CupsFieldBean();
        cupsFieldBean.setCupsField(cupsField);
        ConvertUtil.convertInput(cupsFieldBean);
        /*branchId*/
        if (consumeRefundRequest.getAcqReserved() == null) {
            rglog.error("必须上送branchId");
            throw new BizException(RespCodeEnum.REQUEST_MSG_ERROR.getRespCode(), RespCodeEnum.REQUEST_MSG_ERROR.getRespDesc());
        } else {
            Map<String, Object> reqMap = JSONObject.parseObject(consumeRefundRequest.getAcqReserved());
            for (Map.Entry req : reqMap.entrySet()) {
                xmlTreeUtil.setXmlTreeStringValue((String) req.getKey(), (String) req.getValue());
            }
        }
        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.ESB_ORDER_AMT, StringUtil.leftFillZero(AmountUtil.changeY2F(consumeRefundRequest.getOrderAmt()), CupsParamConstant.AMOUNT_LENGTH));
        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.SERVICE_ID, consumeRefundRequest.getHeader().getTxnNum());
        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.REQUESTER_ID, CupsParamConstant.REQUEST_ID);
        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.VERSION_ID, CupsParamConstant.VERSION_ID);
        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.CHANNEL_ID, CupsParamConstant.CHANNEL_ID);
        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.SERVICE_TIME, consumeRefundRequest.getHeader().getTransDate() + consumeRefundRequest.getHeader().getTransTime());
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, consumeRefundRequest.getHeader().getTxnNum());
        iReturnCode = schedule.callService(dstChannelInfo.getDstServiceName(), 0);
        if (98 == iReturnCode) {
            rglog.error("调用银联cups服务<{}>超时，iReturnCode:<{}>", dstChannelInfo.getDstServiceName(), iReturnCode);
            consumeRefundResponse.setRespCode("98");
            consumeRefundResponse.setRespDesc("交易状态未明");
            chnlBizResponse.setResult(consumeRefundResponse);
            return chnlBizResponse;
        } else if (0 != iReturnCode) {
            rglog.error("调用银联全渠道服务<{}>失败，iReturnCode:<{}>", dstChannelInfo.getDstServiceName(), iReturnCode);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        }

        CupsFieldRspBean cupsFieldRspBean = new CupsFieldRspBean();
        ConvertUtil.convertOutput(cupsFieldRspBean);
        String esbStatus = xmlTreeUtil.getXmlTreeStringValue(CupsTreeNodeConstant.ESB_STATUS);
        rglog.info("esbStatus=<{}>", esbStatus);
        if ("COMPLETE".equals(esbStatus)) {
            //ESB成功
            consumeRefundResponse.setRespCode(CupsParamConstant.SUCCESS_CODE);
            BeanUtil.beanCopy(cupsFieldRspBean.getCupsFieldRsp(), consumeRefundResponse);
        } else if ("FAIL".equals(esbStatus)) {
            //ESB失败
            consumeRefundResponse.setRespCode(xmlTreeUtil.getXmlTreeStringValue(CupsTreeNodeConstant.ESB_RSP_CODE));
            consumeRefundResponse.setRespDesc(xmlTreeUtil.getXmlTreeStringValue(CupsTreeNodeConstant.ESB_RSP_DESC));
        }
        if (consumeRefundResponse.getSettleDate() != null) {
            consumeRefundResponse.setSettleDate(DateShareUtil.changeDate4To8(consumeRefundResponse.getSettleDate()));
        }
        if (CupsParamConstant.SUCCESS_CODE.equals(consumeRefundResponse.getRespCode())) {
            consumeRefundResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            consumeRefundResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            String settleKey = cupsFieldRspBean.getCupsFieldRsp().getTransDateTime() + cupsFieldRspBean.getCupsFieldRsp().getTransDateTime() + consumeRefundRequest.getCupsInstCode() + consumeRefundRequest.getFwdInstCode();
        }
        chnlBizResponse.setResult(consumeRefundResponse);
        return chnlBizResponse;
    }
}
